
#include "LiveServer.h"
#include <memory>
#include <sys/types.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <thread>
#include <functional>
#include "ZYUtils/ZYLog.h"

// ZLMediaKit相关头文件
#include "Util/util.h"
#include "Util/logger.h"
#include "Network/TcpServer.h"
#include "Poller/EventPoller.h"
#include "Common/config.h"
#include "Rtsp/RtspSession.h"
#include "Rtmp/RtmpSession.h"
#include "Http/HttpSession.h"
#include "Shell/ShellSession.h"

using namespace std;
using namespace toolkit;
using namespace mediakit;

namespace ZYLive {
    
    LiveServer::LiveServer(std::string dir) {
        mThreadPool = std::make_shared<ZYUtils::ZYThreadPool>(1);
        mThreadPool->enqueue(std::bind(&LiveServer::startServer, this, std::placeholders::_1), dir);
    }
    
    LiveServer::~LiveServer(){
        if (mThreadID) {
            pthread_kill(mThreadID, SIGINT);
        }
        

        stopServer();
        
        if(mPlayer != nullptr)
            mPlayer.reset();
        
        if(mThreadPool != nullptr)
            mThreadPool.reset();
    }
    
    void LiveServer::initZLMediaKit(const string& ini_file, const string& pem_file) {
        try {
   
            Logger::Instance().add(std::make_shared<ConsoleChannel>("ConsoleChannel", LTrace));
            Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
            
        
            if (!ini_file.empty() && access(ini_file.c_str(), F_OK) == 0) {
                try {
                    loadIniConfig(ini_file.data());
                } catch (...) {
                    ZYUtils::ZY_LOG("无法加载配置文件，使用默认配置");
                }
            }
            
    
            try {
                EventPollerPool::Instance().setPoolSize(std::thread::hardware_concurrency());
            } catch (...) {
               
            }
            
            startServers();
        
            setupSignalHandler();
            
        } catch (std::exception &ex) {
            ZYUtils::ZY_LOG("ZLMediaKit初始化失败: %s", ex.what());
            throw;
        }
    }
    
    void LiveServer::startServers() {
        try {
            // // HTTP服务器
            // auto httpPort = mINI::Instance()["http.port"].as<uint16_t>();
            // if (httpPort > 0) {
            //     try {
            //         auto httpSrv = std::make_shared<TcpServer>();
            //         httpSrv->start<HttpSession>(httpPort);
            //         ZYUtils::ZY_LOG("HTTP服务器启动成功，端口: %d", httpPort);
            //         mServers.push_back(httpSrv);
            //     } catch (std::exception &ex) {
            //         ZYUtils::ZY_LOG("HTTP服务器启动失败: %s", ex.what());
            //     }
            // }
            
            // RTSP服务器
            auto rtspPort = mINI::Instance()["rtsp.port"].as<uint16_t>();
            if (rtspPort > 0) {
                try {
                    auto rtspSrv = std::make_shared<TcpServer>();
                    rtspSrv->start<RtspSession>(rtspPort);
                    ZYUtils::ZY_LOG("RTSP服务器启动成功，端口: %d", rtspPort);
                    mServers.push_back(rtspSrv);
                } catch (std::exception &ex) {
                    ZYUtils::ZY_LOG("RTSP服务器启动失败: %s", ex.what());
                }
            }
            
            // RTMP服务器
            auto rtmpPort = mINI::Instance()["rtmp.port"].as<uint16_t>();
            if (rtmpPort > 0) {
                try {
                    auto rtmpSrv = std::make_shared<TcpServer>();
                    rtmpSrv->start<RtmpSession>(rtmpPort);
                    ZYUtils::ZY_LOG("RTMP服务器启动成功，端口: %d", rtmpPort);
                    mServers.push_back(rtmpSrv);
                } catch (std::exception &ex) {
                    ZYUtils::ZY_LOG("RTMP服务器启动失败: %s", ex.what());
                }
            }
            
        } catch (std::exception &ex) {
            ZYUtils::ZY_LOG("服务器启动失败: %s", ex.what());
            throw;
        }
    }
    
    void LiveServer::setupSignalHandler() {
        static bool s_exit = false;
        signal(SIGINT, [](int) {
            if (!s_exit) {
                s_exit = true;
                ZYUtils::ZY_LOG("收到退出信号...");
                exit(0);
            }
        });
        
        signal(SIGTERM, [](int) {
            if (!s_exit) {
                s_exit = true;
                ZYUtils::ZY_LOG("收到终止信号...");
                exit(0);
            }
        });
    }
    
    void LiveServer::startServer(std::string dir) {
        mThreadID = pthread_self();

        std::string ini_file = dir + "/zlmediakit.ini";
        std::string pem_file = dir + "/zlmediakit.pem";

        try {
            toolkit::mINI::Instance()[mediakit::Http::kRootPath] = dir + "/httpRoot";
            toolkit::mINI::Instance()[mediakit::Protocol::kMP4SavePath] = dir + "/httpRoot";
            toolkit::mINI::Instance()[mediakit::Protocol::kHlsSavePath] = dir + "/httpRoot";
            
            toolkit::mINI::Instance()["http.port"] = 8080;
            toolkit::mINI::Instance()["http.sslport"] = 8443;
            toolkit::mINI::Instance()["rtsp.port"] = 8554;
            toolkit::mINI::Instance()["rtsp.sslport"] = 8332;
            toolkit::mINI::Instance()["rtmp.port"] = 1935;
            toolkit::mINI::Instance()["general.enableVhost"] = 0;
            
            toolkit::mINI::Instance()["protocol.enable_rtsp"] = 1;
            toolkit::mINI::Instance()["protocol.enable_rtmp"] = 1;
            toolkit::mINI::Instance()["protocol.enable_hls"] = 0;      
            toolkit::mINI::Instance()["protocol.enable_mp4"] = 0;    
            

            toolkit::mINI::Instance()["rtsp.directProxy"] = 1;          
            toolkit::mINI::Instance()["rtsp.lowLatency"] = 1;           
            toolkit::mINI::Instance()["rtsp.timeoutSec"] = 5;           
            
            toolkit::mINI::Instance()["rtp.tcpType"] = 0;               
            toolkit::mINI::Instance()["rtp.udpTTL"] = 64;                
            toolkit::mINI::Instance()["rtp.rtpServerPort"] = 10000;     
            toolkit::mINI::Instance()["rtp.rtcpServerPort"] = 10001;    
            
            toolkit::mINI::Instance()["rtp.audioMtuSize"] = 1200;       
            toolkit::mINI::Instance()["rtp.videoMtuSize"] = 1200;        
            toolkit::mINI::Instance()["rtp.clearCount"] = 1;             
            toolkit::mINI::Instance()["rtp.cycleMS"] = 5;                
            
            toolkit::mINI::Instance()["rtsp.authBasic"] = 0;            
            toolkit::mINI::Instance()["rtsp.handshakeSecond"] = 3;       
                
            toolkit::mINI::Instance()["rtp.audioMtuSize"] = 1200;     
            toolkit::mINI::Instance()["rtp.videoMtuSize"] = 1200;
            toolkit::mINI::Instance()["rtp.clearCount"] = 1;          
            toolkit::mINI::Instance()["rtp.cycleMS"] = 10;            
            
            toolkit::mINI::Instance()["general.maxStreamWaitMS"] = 50;    
            toolkit::mINI::Instance()["general.streamNoneReaderDelayMS"] = 200; 
            toolkit::mINI::Instance()["general.resetWhenRePlay"] = 1;     
            toolkit::mINI::Instance()["general.flowThreshold"] = 0;       
            
            toolkit::mINI::Instance()["general.ultraLowDelay"] = 1;      
            toolkit::mINI::Instance()["protocol.pktBufSize"] = 16384;     
            toolkit::mINI::Instance()["protocol.timeoutSec"] = 3;        
            toolkit::mINI::Instance()["protocol.keepAliveSecond"] = 5;  
            
            toolkit::mINI::Instance()["rtp.h264StapA"] = 0;             
            toolkit::mINI::Instance()["rtp.h265StapA"] = 0;             
            toolkit::mINI::Instance()["rtp.gop_cache"] = 0;             
            
            toolkit::mINI::Instance()["hook.enable"] = 0;                 
            toolkit::mINI::Instance()["api.apiDebug"] = 0;                
            toolkit::mINI::Instance()["general.publishToHls"] = 0;        
            toolkit::mINI::Instance()["general.publishToMP4"] = 0;      
            toolkit::mINI::Instance()["general.workThreadNum"] = 1;       
            
            for (auto &pr: toolkit::mINI::Instance()) {
                replace(pr.second, "https://127.0.0.1/", "http://127.0.0.1:8080/");
            }
            
        } catch (std::exception &ex) {
            ZYUtils::ZY_LOG("配置设置失败: %s", ex.what());
        }

        try {
            initZLMediaKit(ini_file, pem_file);
            ZYUtils::ZY_LOG("ZLMediaKit服务器启动成功");
            ZYUtils::ZY_LOG("服务器初始化完成，开始处理请求...");
            
        } catch (std::exception &ex) {
            ZYUtils::ZY_LOG("服务器启动异常: %s", ex.what());
        }
    }
    
    void LiveServer::stopServer() {
        ZYUtils::ZY_LOG("正在停止服务器...");
        
        for (auto& server : mServers) {
            if (server) {
                server.reset();
            }
        }
        mServers.clear();
        
        ZYUtils::ZY_LOG("服务器已停止");
    }
    
    std::string LiveServer::getLiveUrl() {
        return mUrl;
    }

    void LiveServer::createMediaPlayer(std::string url, bool bIsRtmp) {
        generateURL(url, bIsRtmp);

        try {
            mPlayer = std::make_shared<mediakit::MediaPlayer::Ptr>(new mediakit::MediaPlayer());
            mediakit::MediaPlayer::Ptr &player = *(mPlayer.get());

            std::weak_ptr<mediakit::MediaPlayer> weakPlayer = player;
            player->setOnPlayResult([weakPlayer](const toolkit::SockException &ex) {
                auto strongPlayer = weakPlayer.lock();
                if (!strongPlayer) {
                    return;
                }

                if (ex) {
                    ZYUtils::ZY_LOG("播放失败: %s", ex.what());
                    return;
                }
                ZYUtils::ZY_LOG("开始播放");
            });

            player->setOnShutdown([weakPlayer](const toolkit::SockException &ex) {
                auto strongPlayer = weakPlayer.lock();
                if (!strongPlayer) {
                    return;
                }
                ZYUtils::ZY_LOG("播放结束: %s", ex.what());
            });

            (*player)[mediakit::Client::kRtpType] = mediakit::Rtsp::RTP_TCP;
            player->play(mUrl);

            ZYUtils::ZY_LOG("init push server,mUrl:%s", mUrl.c_str());
        } catch (std::exception &ex) {
            ZYUtils::ZY_LOG("创建媒体播放器失败: %s", ex.what());
        }
    }

    void LiveServer::generateURL(std::string url, bool bIsRtmp) {
        struct ifaddrs *interfaces = nullptr;
        struct ifaddrs *temp_addr = nullptr;
        int success = 0;
        std::string ipAddress = "";

        success = getifaddrs(&interfaces);
        if (success == 0) {
            temp_addr = interfaces;
            while (temp_addr != nullptr) {
                if (temp_addr->ifa_addr && temp_addr->ifa_addr->sa_family == AF_INET) {
                    if (strcmp(temp_addr->ifa_name, "lo") != 0) {
                        char addrBuffer[INET_ADDRSTRLEN];
                        inet_ntop(AF_INET, &(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr), addrBuffer, INET_ADDRSTRLEN);
                        ipAddress = addrBuffer;
                        break;
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }
        }

        if (interfaces) {
            freeifaddrs(interfaces);
        }

        if (ipAddress.empty()) {
            ipAddress = "127.0.0.1";
        }

        std::string str;
        if (bIsRtmp == false) {
            str = "rtsp://" + ipAddress + ":8554/" + url;
        } else {
            str = "rtmp://" + ipAddress + ":1935/" + url;
        }

        mIPAddr = ipAddress;
        mUrl = str;
    }
    
    // void LiveServer::start(std::string dir) {
    //     startServer(dir);
    // }
}